package com.jiawa.train.business.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jiawa.train.business.domain.po.DailyTrain;
import com.jiawa.train.business.domain.po.Train;
import com.jiawa.train.business.mapper.DailyTrainMapper;
import com.jiawa.train.business.req.DailyTrainQueryReq;
import com.jiawa.train.business.req.DailyTrainSaveReq;
import com.jiawa.train.business.resp.DailyTrainQueryResp;
import com.jiawa.train.business.service.*;
import com.jiawa.train.common.exception.BusinessException;
import com.jiawa.train.common.exception.BusinessExceptionEnum;
import com.jiawa.train.common.resp.PageResp;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 每日车次 服务实现类
 * </p>
 *
 * @author hrz
 * @since 2025-09-07
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class DailyTrainServiceImpl extends ServiceImpl<DailyTrainMapper, DailyTrain> implements IDailyTrainService {

    private final ITrainService trainService;
    private final IDailyTrainStationService dailyTrainStationService;
    private final IDailyTrainCarriageService dailyTrainCarriageService;
    private final IDailyTrainSeatService dailyTrainSeatService;
    private final IDailyTrainTicketService dailyTrainTicketService;
    private final ISkTokenService skTokenService;

    @Override
    public void saveDailyTrain(DailyTrainSaveReq req) {
        DailyTrain dailyTrain = BeanUtil.copyProperties(req, DailyTrain.class);
        //2.检查是否是修改操作
        if(ObjectUtil.isNotEmpty(req.getId())){
            //3.修改操作
            dailyTrain.setUpdateTime(LocalDateTime.now());
            this.updateById(dailyTrain);
        }else{
            //4.新增操作
            //1.唯一性校验
            DailyTrain one = this.lambdaQuery()
                    .eq(DailyTrain::getDate, req.getDate())
                    .eq(DailyTrain::getCode, req.getCode())
                    .one();
            if(ObjectUtil.isNotEmpty(one) || one != null){
                throw new BusinessException(BusinessExceptionEnum.BUSINESS_DAILY_TRAIN_UNIQUE_ERROR);
            }
            dailyTrain.setCreateTime(LocalDateTime.now());
            dailyTrain.setUpdateTime(LocalDateTime.now());
            this.save(dailyTrain);
        }
    }

    @Override
    public PageResp<DailyTrainQueryResp> queryList(DailyTrainQueryReq req) {
        Page<DailyTrain> page = this.lambdaQuery()
                .eq(req.getDate()!=null,DailyTrain::getDate, req.getDate())
                .eq(req.getCode()!=null,DailyTrain::getCode, req.getCode())
                .orderByDesc(req.getDate()!=null,DailyTrain::getDate)
                .orderByAsc(req.getCode()!=null,DailyTrain::getCode)
                .page(new Page<>(req.getPage(), req.getSize()));
        List<DailyTrain> records = page.getRecords();
        if(ObjectUtil.isEmpty(records)){
            PageResp<DailyTrainQueryResp> r = new PageResp<>();
            r.setList(new ArrayList<>());
            r.setTotal(0L);
            return r;
        }
        List<DailyTrainQueryResp> respList = BeanUtil.copyToList(records, DailyTrainQueryResp.class);
        PageResp<DailyTrainQueryResp> r = new PageResp<>();
        r.setList(respList);
        r.setTotal(page.getTotal());
        return r;
    }

    @Override
    public void delete(Long id) {
        if(ObjectUtil.isEmpty(id)){
            throw new BusinessException(BusinessExceptionEnum.ID_NULL);
        }
        this.removeById(id);
    }

    /*
    * 生成每日车次信息 - 车次 车站 车厢 座位
    * @param date 日期
    * */
    @Transactional
    @Override
    public void generate(Date date) {
        //1.查询所有车次信息
        List<Train> trainList = trainService.selectAll();
        if(CollUtil.isEmpty(trainList)){
            log.error("车次信息为空");
            return;
        }

        log.info("生成车次开始,日期:{}", date);
        //2.循环所有车次生成今日车次信息
        for(Train train : trainList){
            log.info("生成车次开始,日期:{},车次:{}", date, train.getCode());

            //3.清空本日期的车次信息
            this.lambdaUpdate()
                    .eq(DailyTrain::getDate, date)
                    .eq(DailyTrain::getCode, train.getCode())
                    .remove();
            //4.再生成该日期的车次信息
            DailyTrain dailyTrain = BeanUtil.copyProperties(train, DailyTrain.class);
            dailyTrain.setId(null);
            dailyTrain.setDate(date);
            dailyTrain.setUpdateTime(LocalDateTime.now());
            dailyTrain.setCreateTime(LocalDateTime.now());
            this.save(dailyTrain);
            log.info("生成车站开始,日期:{}", date);
            dailyTrainStationService.genDaily(date,train.getCode());
            log.info("生成车站结束,日期:{}", date);
            log.info("生成车厢开始,日期:{}", date);
            dailyTrainCarriageService.genDaily(date,train.getCode());
            log.info("生成车厢结束,日期:{}", date);
            log.info("生成座位开始,日期:{}", date);
            dailyTrainSeatService.genDaily(date,train.getCode());
            log.info("生成座位结束,日期:{}", date);
            log.info("生成改车次余票开始,日期:{}", date);
            dailyTrainTicketService.genDaily(dailyTrain.getType(),date,train.getCode());
            log.info("生成余票结束,日期:{}", date);
            log.info("生成令牌开始,日期:{}", date);
            skTokenService.genDaily(date,train.getCode());
            log.info("生成令牌结束,日期:{}", date);
            log.info("生成车次结束,日期:{},车次:{}", date, train.getCode());
        }
        log.info("生成车次结束,日期:{}", date);
    }
}
